package com.beeantec.jnrerc.config.mybatisplus;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.FieldStrategy;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert;
import com.baomidou.mybatisplus.generator.config.po.TableFill;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.config.rules.IColumnType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;

import com.beeantec.jnrerc.core.enums.CsmbEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 构建一个代码生成器
 *
 * @author : NanCheung
 */
public class MpGeneratorResolver {

    MpGeneratorBuilder builder;

    private static final String OUTPUT_DIR_PATH = getOutputDirPath();
    private static Logger log = LoggerFactory.getLogger(MpGeneratorResolver.class);


    /**
     * 生成器
     */
    protected void execute() {
        long startTime = System.currentTimeMillis();

        //利用并行流生成文件
        Arrays.stream(builder.getCsmb()).collect(Collectors.toList()).parallelStream()
                .map(this::getAutoGenerator)
                .collect(Collectors.toList()).parallelStream()
                .forEach(autoGenerator -> {
                    Map<String, String> pathInfo = autoGenerator.getPackageInfo().getPathInfo();
                    log.info("{}",pathInfo);
                    autoGenerator.execute();
                });

        log.info("耗时：" + (System.currentTimeMillis() - startTime) / 1000 + "秒");
    }

    /**
     * 获得通用自定义配置项
     *
     * @return 此次的配置项
     */
    private AutoGenerator getAutoGenerator(CsmbEnum csmbEnum) {
        return new AutoGenerator()
                .setGlobalConfig(globalConfig())
                .setDataSource(dataSourceConfig())
                .setStrategy(strategyConfig())
                .setPackageInfo(packageInfo(csmbEnum))
                .setTemplate(templateConfig(csmbEnum))
                .setCfg(new InjectionConfig() {
                    @Override
                    public void initMap() {

                    }
                })
                //.setTemplateEngine(new FreemarkerTemplateEngine())
                ;
    }

    /**
     * 获取文件输出路径
     */
    private static String getOutputDirPath() {
        //生成文件的输出目录，通常设置为代码源路径
        String outputDir;
        String path = "\\";
        String osName = System.getProperty("os.name");
        if (osName.startsWith("Mac OS")) {
            path = "//";
        }
        try {
//            outputDir = new File("").getCanonicalFile().getParentFile().getParent();
            outputDir = new File("").getCanonicalFile().getCanonicalPath();

        } catch (IOException e) {
            throw new RuntimeException("-------------无法读取项目路径！-------------", e);
        }

        return outputDir+path;
    }

    /**
     * 配置自定义模板
     * <p>自定义模板配置，可以 copy 源码 mybatis-plus/src/main/resources/templates 下面内容修改</p>
     */
    private TemplateConfig templateConfig(CsmbEnum csmbEnum) {
        TemplateConfig tc = new TemplateConfig();
        tc.setEntity(null).setController(null).setMapper(null).setService(null).setServiceImpl(null).setXml(null);
        switch (csmbEnum) {
            case entity:
                tc.setEntity("/templates/entity.java");
                return tc;
            case mapper:
                tc.setMapper("/templates/mapper.java");
                return tc;
            case mapper_xml:
                tc.setXml("/templates/mapper.xml");
                return tc;
            default:
                return tc;
        }
    }

    /**
     * 获取TableFill策略
     */
    private List<TableFill> getTableFills() {
        // 自定义需要填充的字段
        List<TableFill> tableFillList = new ArrayList<>();
        tableFillList.add(new TableFill("create_time", FieldFill.INSERT));
        tableFillList.add(new TableFill("update_time", FieldFill.INSERT_UPDATE));
        return tableFillList;
    }

    /**
     * 全局配置
     *
     * @return 配置对象
     */
    private GlobalConfig globalConfig() {

        return new GlobalConfig()
                .setOutputDir(OUTPUT_DIR_PATH)
                .setFileOverride(true)
                //开启ActiveRecord特性
                .setActiveRecord(builder.getActiveRecord())
                // XML 二级缓存
                .setEnableCache(false)
                // XML ResultMap
                .setBaseResultMap(true)
                //时间类型
                .setDateType(DateType.ONLY_DATE)
                // XML columList
                .setBaseColumnList(true)
                //生成完成后是否打开窗口
                .setOpen(builder.getOpenInExplorer())
                .setSwagger2(builder.getSwagger2())
                .setAuthor(builder.getAuthor());
    }

    /**
     * 配置数据库连接
     */
    private DataSourceConfig dataSourceConfig() {
        // 数据源配置
        return new DataSourceConfig()
                .setDbType(DbType.MYSQL)
                // 转换类型
                .setTypeConvert(new MySqlTypeConvert() {
                    @Override
                    public IColumnType processTypeConvert(GlobalConfig globalConfig, String fieldType) {
                        if (fieldType.toLowerCase().equals("bit")) {
                            return DbColumnType.BOOLEAN;
                        }
                        if (fieldType.toLowerCase().equals("tinyint")) {
                            return DbColumnType.BOOLEAN;
                        }
                        /*if (fieldType.toLowerCase().equals("date")) {
                            return DbColumnType.LOCAL_DATE;
                        }
                        if (fieldType.toLowerCase().equals("time")) {
                            return DbColumnType.LOCAL_TIME;
                        }
                        if (fieldType.toLowerCase().equals("datetime")) {
                            return DbColumnType.LOCAL_DATE_TIME;
                        }*/
                        if (fieldType.toLowerCase().contains("blob")) {
                            return DbColumnType.STRING;
                        }
                        return super.processTypeConvert(globalConfig, fieldType);
                    }
                })
                .setDriverName("com.mysql.cj.jdbc.Driver")
                .setUsername(builder.getDataBaseUserName())
                .setPassword(builder.getDataBasePassword())
                .setUrl(builder.getDataBaseUrl());
    }

    /**
     * 配置策略
     */
    private StrategyConfig strategyConfig() {
        return new StrategyConfig()
                .setTableFillList(getTableFills())
                // 去除表前缀
                .setTablePrefix(builder.getTableNamePrefix())
                // 表名生成策略
                .setNaming(NamingStrategy.underline_to_camel)
                // 需要生成的表
                .setInclude(builder.getTableNames())
                // 自定义 controller 父类
                .setSuperControllerClass("")
                //是否使用lombok
                .setEntityLombokModel(builder.getLombok())
                //【实体】是否生成字段常量（默认 false）
                .setEntityColumnConstant(true)
                // 【实体】是否为构建者模型（默认 false）
                .setEntityBuilderModel(true)
                // Boolean类型字段是否移除is前缀处理
                .setEntityBooleanColumnRemoveIsPrefix(true)
                //Controller使用@RestController注解
                .setRestControllerStyle(true);
    }
//D:\IdeaProjects\jnrerc-api\jnrerc-mbg\src\main\resources
 //   D:\IdeaProjects\jnrerc-api\jnrerc-mbg\src\main\java\com\beeantec\jnrerc\mapper
    //D:\IdeaProjects\jnrerc-api\jnrerc-mbg\src\main\java\com\beeantec\jnrerc\model
    /**
     * 包配置
     */
    /**
     * Mac和window生成目录规则不一致
     */
    private HashMap<String, String> getPackage() {
        String beanPath = "\\src\\main\\java\\com\\beeantec\\jnrerc\\entity";
        String mapperPath = "\\src\\main\\java\\com\\beeantec\\jnrerc\\mapper";
        String mapperXmlPath = "\\src\\main\\resources\\mapper";
        String osName = System.getProperty("os.name");
        if (osName.startsWith("Mac OS")) {
            beanPath = "//src//main//java//com//beeantec//jnrerc//entity";
            mapperPath = "//src//main//java//com//beeantec//jnrerc//mapper";
            mapperXmlPath = "//src//main//resources//mapper";
        }
        HashMap<String, String> map = new HashMap<>(16);
        map.put("entity", beanPath);
        map.put("mapper", mapperPath);
        map.put("mapper_xml", mapperXmlPath);
        return map;

    }

    /**
     * 包配置
     */
    private PackageConfig packageInfo(CsmbEnum csmbEnum) {

        Map<String, String> pathInfo = new HashMap<>();
        HashMap<String, String> packageMap = getPackage();
        switch (csmbEnum) {
            case entity:
                pathInfo.put(ConstVal.ENTITY_PATH, OUTPUT_DIR_PATH + packageMap.get("entity"));
                break;
            case mapper:
                pathInfo.put(ConstVal.MAPPER_PATH, OUTPUT_DIR_PATH + packageMap.get("mapper") );
                break;
            case mapper_xml:
                pathInfo.put(ConstVal.XML_PATH, OUTPUT_DIR_PATH + packageMap.get("mapper_xml") );
                break;
            default:
                break;
        }
        // 包配置
        return new PackageConfig()
                .setParent(null)
                .setPathInfo(pathInfo)
                //配置实体类的包
                .setEntity("com.beeantec.jnrerc.entity")
                //mapper接口包
                .setMapper("com.beeantec.jnrerc.mapper")
                //xml包
                .setXml("mapper");
    }
}
